package work;

import util.CollectionUtils;
import util.FileTool;
import util.KMeansClustering;
import util.StopWordUtil;

import java.util.*;

/**
 * @author ：hzs
 * @date ：Created in 2021/2/18 15:56
 * @description：参考文献题目聚类
 * @modified By：
 * @version: $
 */
public class Work3 extends KMeansClustering<RefC> {

    @Override
    public double similarScore(RefC o1, RefC o2) {
        return getDistance(o1.coordinate, o2.coordinate);
    }

    @Override
    public boolean equals(RefC o1, RefC o2) {
        for (int i = 0; i < o1.coordinate.length; i++) {
            if (!o1.coordinate[i].equals(o2.coordinate[i])) {
                return false;
            }
        }
        return true;
    }

    @Override
    public RefC getCenterT(List<RefC> list) {
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        Double[] result = new Double[list.get(0).coordinate.length];
        for (int i1 = 0; i1 < result.length; i1++) {
            result[i1] = new Double(0);
        }
        // 初始化结束
        for (RefC refC : list) {
            for (int i = 0; i < refC.coordinate.length; i++) {
                result[i] += refC.coordinate[i];
            }
        }
        for (int i = 0; i < result.length; i++) {
            result[i] /= list.size();
        }
        RefC refC = new RefC();
        refC.coordinate = result;
        return refC;
    }

    public List<String> readTitle() {
        List<String> titles = FileTool.getFileLines(this.getClass().getClassLoader().getResource("Titles").getPath());
        return titles;
    }

    public Map<String, List<String>> removeStopWords(List<String> titles) {
        Set<String> stopWords = StopWordUtil.getStopWordsEN();
        Map<String, List<String>> result = new HashMap<>(titles.size());
        for (String title : titles) {
            title = title.toLowerCase();
            String[] s = title.split(" ");
            List<String> list = new ArrayList<>();
            for (String s1 : s) {
                String s2 = s1.replaceAll("[^0-9^a-z^A-Z]", "");
                if (!stopWords.contains(s2)) {
                    list.add(s2);
                }
            }
            result.put(title, list);
        }
        return result;
    }

    /**
     *
     * @param titles k:题目，v：题目的词表
     * @return
     */
    private Map<String, Double[]> getCoordinate(Map<String, List<String>> titles) {
        // k：单词，v：单词的索引号
        Map<String, Integer> words = new HashMap<>();
        int i = 0;
        for (List<String> title : titles.values()) {
            for (String s : title) {
                if (!words.containsKey(s)) {
                    words.put(s, i++);
                }
            }
        }
        // k:单词，v：idf
        Map<String, Double> idfs = new HashMap<>();
        for (Map.Entry<String, Integer> entry : words.entrySet()) {
            String key = entry.getKey();
            int count = 0;
            for (String s : titles.keySet()) {
                if (s.contains(key)) {
                    count++;
                }
            }
            idfs.put(key, Math.log10(titles.size() / (count + 1)));
        }
        Map<String, Double[]> result = new HashMap<>();
        for (Map.Entry<String, List<String>> entry : titles.entrySet()) {
            Double[] coordinate = new Double[i];
            for (int i1 = 0; i1 < coordinate.length; i1++) {
                coordinate[i1] = new Double(0F);
            }
            for (String s : entry.getValue()) {
                int count = 0;
                for (String s1 : entry.getValue()) {
                    if (s.equals(s1)) {
                        count++;
                    }
                }
                double tf = 1.0 * count / entry.getValue().size();
                double idf = idfs.get(s);
                coordinate[words.get(s)] = tf * idf;
            }
            result.put(entry.getKey(), coordinate);
        }
        return result;
    }

    private double getDistance(Double[] coordinate1, Double[] coordinate2) {
        double a = 0;
        double b = 0;
        double c = 0;
        for (int i = 0; i < coordinate1.length; i++) {
            a += coordinate1[i] * coordinate1[i];
            b += coordinate2[i] * coordinate2[i];
            c += coordinate1[i] * coordinate2[i];
        }
        if (a == 0 || b == 0) {
            return -1.0;
        }
        return c / (Math.sqrt(a) * Math.sqrt(b));
    }

    public void clusterTitle(List<List<String>> titles) {

    }

    public static void main(String[] args) {
        Work3 work3 = new Work3();
        List<String> list = work3.readTitle();
        Map<String, List<String>> map = work3.removeStopWords(list);
        Map<String, Double[]> coordinate = work3.getCoordinate(map);
        for (Map.Entry<String, Double[]> entry : coordinate.entrySet()) {
            RefC refC = new RefC();
            refC.title = entry.getKey();
            refC.coordinate = entry.getValue();
            work3.addRecord(refC);
        }
        List<List<RefC>> clustering = work3.clustering();
        int i = 1;
        for (List<RefC> refCS : clustering) {
            System.out.println("第" + i++ + "类：");
            for (RefC refC : refCS) {
                System.out.println(refC.title);
            }
        }
//        work3.clusterTitle(null);

    }

}

class RefC {
    String title;
    Double[] coordinate;
}